package com.ubb.dbms.core.parser.visitors;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.sf.jsqlparser.expression.AllComparisonExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.InverseExpression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.SubSelect;

import com.ubb.dbms.domain.queryData.Condition;
import com.ubb.dbms.domain.queryData.LogicalOperator;

public class SQLExpressionVisitor implements ExpressionVisitor, ItemsListVisitor {
	
	private List<String> projectionList;
	private List<Condition> conditionList;
	private LogicalOperator logicalOperator;
	
	public SQLExpressionVisitor() {
		projectionList = new ArrayList<String>();
		conditionList = new ArrayList<Condition>();
		logicalOperator = null;
	}
	
	public void visitExpression(BinaryExpression binaryExpression) {
		SQLConditionVisitor leftConditionVisitor = new SQLConditionVisitor();
		SQLConditionVisitor rightConditionVisitor = new SQLConditionVisitor();
		binaryExpression.getLeftExpression().accept(leftConditionVisitor);
		binaryExpression.getRightExpression().accept(rightConditionVisitor);
		conditionList.add(leftConditionVisitor.getCondition());
		conditionList.add(rightConditionVisitor.getCondition());
	}
	
	public void visitCondition(BinaryExpression binaryExpression) {
		SQLConditionVisitor conditionVisitor = new SQLConditionVisitor();
		binaryExpression.accept(conditionVisitor);
		conditionList.add(conditionVisitor.getCondition());
	}
	
	@Override
	public void visit(ExpressionList expressionList) {
		for (Iterator iter = expressionList.getExpressions().iterator(); iter.hasNext();) {
			Expression expression = (Expression) iter.next();
			expression.accept(this);
		}	
	}

	@Override
	public void visit(Column column) {
		String projectionItem = column.getWholeColumnName();
		projectionList.add(projectionItem);
	}
	
	/*
	 * return a projection array
	 */
	public String[] getProjections() {
		String[] projections = new String[projectionList.size()];
		projectionList.toArray(projections);
		return projections;
	}
	
	public Condition[] getConditions() {
		Condition[] conditions = new Condition[conditionList.size()];
		conditionList.toArray(conditions);
		return conditions;
	}
	
	public LogicalOperator getLogicalOperator() {
		return this.logicalOperator;
	}
	
	@Override
	public void visit(AndExpression andExpression) {
		logicalOperator = LogicalOperator.AND;
		visitExpression(andExpression);
	}
	
	@Override
	public void visit(OrExpression orExpression) {
		logicalOperator = LogicalOperator.OR;
		visitExpression(orExpression);
	}
	
	@Override
	public void visit(Parenthesis parenthesis) {
		parenthesis.getExpression().accept(this);
	}
	
	@Override
	public void visit(EqualsTo equalsTo) {
		visitCondition(equalsTo);
	}
	
	@Override
	public void visit(NotEqualsTo notEqualsTo) {
		visitCondition(notEqualsTo);
	}
	
	@Override
	public void visit(GreaterThan greaterThan) {
		visitCondition(greaterThan);
	}
	
	@Override
	public void visit(GreaterThanEquals greaterThanEquals) {
		visitCondition(greaterThanEquals);
	}
	
	@Override
	public void visit(MinorThan minorThan) {
		visitCondition(minorThan);
	}

	@Override
	public void visit(MinorThanEquals minorThanEquals) {
		visitCondition(minorThanEquals);
	}
	
	@Override
	public void visit(LikeExpression likeExpression) {
		visitCondition(likeExpression);
	}
	
	@Override
	public void visit(DoubleValue doubleValue) {
		// TODO Auto-generated method stub
	}

	@Override
	public void visit(LongValue longValue) {
		// TODO Auto-generated method stub
	}

	@Override
	public void visit(DateValue dateValue) {
		// TODO Auto-generated method stub
	}

	@Override
	public void visit(TimeValue timeValue) {
		// TODO Auto-generated method stub
	}

	@Override
	public void visit(TimestampValue timestampValue) {
		// TODO Auto-generated method stub
	}

	@Override
	public void visit(StringValue stringValue) {
		// TODO Auto-generated method stub
	}
	
	@Override
	public void visit(NullValue arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Function arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(InverseExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(JdbcParameter arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Addition arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Division arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Multiplication arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Subtraction arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Between arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(InExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(IsNullExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(SubSelect arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(CaseExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(WhenClause arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(ExistsExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AllComparisonExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AnyComparisonExpression arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Concat arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Matches arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(BitwiseAnd arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(BitwiseOr arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(BitwiseXor arg0) {
		// TODO Auto-generated method stub

	}

}
